#include <exception>
#include <format>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>

const int DefaultStartingSalary{30'000};
const int FirstEmployeeNumber{1'000};

class Employee {
  private:
    /* data */
    std::string m_firstName;
    std::string m_lastName;
    int m_employeeNumber;
    bool m_isHired{false};
    int m_salary{DefaultStartingSalary};

  public:
    Employee(const std::string &firstname, const std::string &lastname);
    void promote(int raiseAmount = DefaultStartingSalary);
    void demote(int demeritAmount = DefaultStartingSalary);
    void hire();
    void fire();
    void display() const;
    void setFirstName(const std::string &firstname);
    void setLastName(const std::string &lastname);
    const std::string getFirstName() const;
    const std::string getLastName() const;
    void setEmployeeNumber(int employeeNumber);
    int getEmployeeNumber() const;
    void setSalary(int newSalary);
    int getSalary() const;
    bool isHired() const;
};

Employee::Employee(const std::string &firstname, const std::string &lastname)
    : m_firstName{firstname}, m_lastName{lastname} {}

void Employee::promote(int raiseAmount) {
    setSalary(getSalary() + raiseAmount);
}

void Employee::demote(int demeritAmount) {
    setSalary(getSalary() - demeritAmount);
}

void Employee::hire() { m_isHired = true; }

void Employee::fire() { m_isHired = false; }

void Employee::display() const {
    std::cout << std::format("职员: {} {}\n", getLastName(), getFirstName());
    std::cout << "-------------------------------------------\n";
    std::cout << std::format("雇佣状态: {}\n", isHired() ? "已雇佣" : "未雇佣");
    std::cout << std::format("员工编号: {}\n", getEmployeeNumber());
    std::cout << std::format("薪水: ${}\n", getSalary());
    std::cout << "-------------------------------------------" << std::endl;
}

void Employee::setFirstName(const std::string &firstname) {
    m_firstName = firstname;
}

void Employee::setLastName(const std::string &lastname) {
    m_lastName = lastname;
}

const std::string Employee::getFirstName() const { return m_firstName; }

const std::string Employee::getLastName() const { return m_lastName; }

void Employee::setEmployeeNumber(int employeeNumber) {
    m_employeeNumber = employeeNumber;
}

int Employee::getEmployeeNumber() const { return m_employeeNumber; }

void Employee::setSalary(int newSalary) {
    if (newSalary < 0) {
        std::cout << "薪水不能为负数" << std::endl;
        return;
    }
    m_salary = newSalary;
}

int Employee::getSalary() const { return m_salary; }

bool Employee::isHired() const { return m_isHired; }

class Database {
  private:
    /* data */
    std::vector<Employee> m_employees;
    int m_nextEmployeeNumber{FirstEmployeeNumber};

  public:
    Employee &addEmployee(const std::string &firstName,
                          const std::string &lastName);
    Employee &getEmployee(int employeeNumber);
    Employee &getEmployee(const std::string &firstName,
                          const std::string &lastName);
    void displayAll() const;
    void displayCurrent() const;
    void displayFormer() const;
};

Employee &Database::addEmployee(const std::string &firstName,
                                const std::string &lastName) {
    // TODO: 在此处插入 return 语句
    Employee theEmployee{firstName, lastName};
    theEmployee.setEmployeeNumber(m_nextEmployeeNumber++);
    theEmployee.hire();
    m_employees.push_back(theEmployee);
    return m_employees.back();
}

Employee &Database::getEmployee(int employeeNumber) {
    // TODO: 在此处插入 return 语句
    for (auto &employee : m_employees) {
        if (employee.getEmployeeNumber() == employeeNumber)
            return employee;
    }
    throw std::invalid_argument("找不到员工");
}

Employee &Database::getEmployee(const std::string &firstName,
                                const std::string &lastName) {
    // TODO: 在此处插入 return 语句
    for (auto &employee : m_employees) {
        if (employee.getFirstName() == firstName &&
            employee.getLastName() == lastName)
            return employee;
    }
    throw std::logic_error("找不到员工");
}

void Database::displayAll() const {
    for (auto &employee : m_employees) {
        employee.display();
    }

    std::cout << std::endl;
    std::cout << "总共员工数：" << m_employees.size() << std::endl;
}

void Database::displayCurrent() const {
    for (auto &employee : m_employees) {
        if (employee.isHired())
            employee.display();
    }
}

void Database::displayFormer() const {
    for (auto &employee : m_employees) {
        if (!employee.isHired())
            employee.display();
    }
}

int displayMenu();
void doHire(Database &db);
void doFire(Database &db);
void doPromote(Database &db);

int displayMenu() {
    int selection{0};
    std::cout << std::endl;
    std::cout << "职员数据库" << std::endl;
    std::cout << "----------------" << std::endl;
    std::cout << "1.雇佣新职员" << std::endl;
    std::cout << "2.解雇职员" << std::endl;
    std::cout << "3.提升职员" << std::endl;
    std::cout << "4.显示所有职员" << std::endl;
    std::cout << "5.显示当前职员" << std::endl;
    std::cout << "6.显示前职员" << std::endl;
    std::cout << "0.退出" << std::endl;
    std::cout << "---->";
    std::cin >> selection;
    return selection;
}

void doHire(Database &db) {
    std::string firstName, lastName;
    std::cout << "请输入职员名：";
    std::cin >> firstName;
    std::cout << "请输入姓氏：";
    std::cin >> lastName;
    Employee &newHire = db.addEmployee(firstName, lastName);
    newHire.setSalary(3000); // 薪水默认为3000
    std::cout << std::format("雇佣了新员工: {} {}\n", newHire.getFirstName(),
                             newHire.getLastName());
}

void doFire(Database &db) {
    int employeeNumber;
    std::cout << "请输入要解雇的职员编号：";
    std::cin >> employeeNumber;
    try {
        Employee &fired = db.getEmployee(employeeNumber);
        if (fired.isHired()) {
            fired.fire();
            std::cout << std::format("解雇了员工: {} {}\n",
                                     fired.getFirstName(), fired.getLastName());
        } else
            std::cout << "该员工已被解雇" << std::endl;
    } catch (const std::logic_error &e) {
        std::cout << e.what() << std::endl;
    }
}

void doPromote(Database &db) {
    int employeeNumber;
    std::cout << "请输入要提升的职员编号：";
    std::cin >> employeeNumber;
    try {
        Employee &promoted = db.getEmployee(employeeNumber);
        if (promoted.isHired()) {
            promoted.setSalary(promoted.getSalary() * 2);
            std::cout << std::format("提升了员工: {} {}\n",
                                     promoted.getFirstName(),
                                     promoted.getLastName());
        } else
            std::cout << "该员工已被解雇" << std::endl;
    } catch (const std::logic_error &e) {
        std::cout << e.what() << std::endl;
    }
}

int main() {
    Database employeeDB;
    bool done{false};
    while (!done) {
        int selection{displayMenu()};
        switch (selection) {
        case 0:
            /* code */
            done = true;
            break;
        case 1:
            /* code */
            doHire(employeeDB);
            break;
        case 2:
            /* code */
            doFire(employeeDB);
            break;
        case 3:
            /* code */
            doPromote(employeeDB);
            break;
        case 4:
            /* code */
            employeeDB.displayAll();
            break;
        case 5:
            /* code */
            employeeDB.displayCurrent();
            break;
        case 6:
            /* code */
            employeeDB.displayFormer();
            break;
        default:
            std::cout << "未知选项" << std::endl;
            break;
        }
    }
}